package com.kt.common.clazz.entrust

import com.kt.common.clazz.inlineclazz.Foo
import kotlin.properties.Delegates
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty


fun main() {
    /* val user = User()
     user.name = "first"
     user.name = "second"

     user.age = 10
     user.age = 29*/
    /*val classWithDelegate = ClassWithDelegate(99)
    val myClass = MyClass(1, classWithDelegate)
    println(myClass.delegatedToMember)
    println(myClass.delegatedToTopLevel)
    println(myClass.delegatedToAnotherClass)*/

    /*val myClass1 = MyClass1()
    myClass1.oldName =10
    println(myClass1.newName)
    myClass1.newName  =20
    println(myClass1.newName)*/

    /*val user = UserJson(mapOf(
        "name" to "John Doe",
        "age"  to 25
    ))*/

    ResourceDelegate()

}


class User {

    //定义可观察属性 Observable
    //no name -> first -> second
    var name: String by Delegates.observable("<no name>") { prop, old, new ->
        println("$prop ->$old -> $new")
    }

    //截获赋值并“否决”上一个赋的值
    //1->10 1-29
    var age: Int by Delegates.vetoable(1) { property, oldValue, newValue ->
        println("$property ->$oldValue -> $newValue")
        oldValue == newValue
    }
}


//委托给另一个属性
/**
 * 允许范围：
 * 顶层属性
 * 同一个类的成员或扩展属性
 * 另一个类的成员或扩展属性
 */
var topLevelInt: Int = 19

class ClassWithDelegate(var anotherClassInt: Int) {}

class MyClass(var memberInt: Int, val anotherClassInstance: ClassWithDelegate) {
    var delegatedToMember: Int by this::memberInt
    var delegatedToTopLevel: Int by ::topLevelInt


    val delegatedToAnotherClass: Int by anotherClassInstance::anotherClassInt
}

var MyClass.extDelegated: Int by ::topLevelInt

//eg.委托给另一个属性的应用
class MyClass1 {

    @Deprecated("this filed is Deprecated since kotlin 1.3")
    var oldName: Int = 0

    //此属性要兼容之前的属性 ,向上兼容
    var newName: Int by this::oldName
}

/**
 * 将属性储存在映射中
 */

class UserJson(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}

/**
 * 局部委托属性
 */

/*
fun example(computeFoo: () -> Foo) {
    val memoizedFoo by lazy(computeFoo)

    if (someCondition && memoizedFoo.isValid()) {
        memoizedFoo.doSomething() //只会在第一次计算，如果someCondition = false 根本不会调用
    }
}*/


class Resource

class Owner {
    val valResource: Resource by ResourceDelegate()
}

/*
class ResourceDelegate {
    operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
        return Resource()
    }
}*/
class ResourceDelegate(private var resource: Resource = Resource()) {
    operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
        return resource
    }
    operator fun setValue(thisRef: Owner, property: KProperty<*>, value: Any?) {
        if (value is Resource) {
            resource = value
        }
    }
}

fun resourceDelegate(): ReadWriteProperty<Any?, Int> =
    object : ReadWriteProperty<Any?, Int> {
        var curValue = 0
        override fun getValue(thisRef: Any?, property: KProperty<*>): Int = curValue
        override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
            curValue = value
        }
    }

val readOnly: Int by resourceDelegate()  // ReadWriteProperty as val
var readWrite: Int by resourceDelegate()


//只读属性使用的是ReadOnlyProperty
/*
class ResourceDelegate<T> : ReadOnlyProperty<MyUI, T> {
    override fun getValue(thisRef: MyUI, property: KProperty<*>): T {  }
}

class ResourceLoader<T>(id: ResourceID<T>) {
    operator fun provideDelegate(
        thisRef: MyUI,
        prop: KProperty<*>
    ): ReadOnlyProperty<MyUI, T> {
        checkProperty(thisRef, prop.name)
        // 创建委托
        return ResourceDelegate()
    }

    private fun checkProperty(thisRef: MyUI, name: String) { …… }
}

class MyUI {
    fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { …… }

    val image by bindResource(ResourceID.image_id)
    val text by bindResource(ResourceID.text_id)
}
*/
